package com.hihonor;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ReflectUtil;
import com.hihonor.db.DsUtil;
import com.hihonor.excel.ExcelUtil;
import com.hihonor.model.EsdEmp;
import com.hihonor.sound.SoundUtil;
import com.hihonor.swing.SettingDialog;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 李志雄
 * @since 2023-10-13
 */
public class Main extends JFrame {
    /**
     * 初始化所有的部门
     */
    private List<String> depList = new ArrayList<>();
    private final JComboBox<String> depCmp = new JComboBox<>();

    private final JButton startBtn = new JButton("开始记录");

    private final JButton stopBtn = new JButton("停止记录");

    private final JButton exportBtn = new JButton("导出文件");

    private final JTextField scanField = new JTextField("", 30);

    private final JPanel buttonPanel = new JPanel();

    private final String[] tableColumn = {"姓名", "工号", "一级部门", "二级部门", "三级部门", "工段", "车间"};

    private final DefaultTableModel defaultTableModel = new DefaultTableModel(new String[0][], tableColumn) {
        @Override
        public boolean isCellEditable(int row, int column) {
            // 禁止编辑
            return false;
        }
    };

    private final JTable table = new JTable(defaultTableModel);

    /**
     * 所有刷卡成功的用户记录
     */
    private List<String> scanSuccessUser = new ArrayList<>();

    public Main(String title) {
        this.setTitle(title);
        Toolkit toolkit = getToolkit();
        Dimension dimension = toolkit.getScreenSize();
        setSize(dimension.width / 2, dimension.height / 2);
        setLocation((dimension.width - getWidth()) / 2, (dimension.height - getHeight()) / 2);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    }

    public static void main(String[] args) {
        Main main = new Main("ESD刷卡记录小程序");

        // 设置页面元素
        main.setItems();

        // 设置字体
        main.setFont();

        // 初始化状态栏
        main.initStatusBar();

        // 设置窗口可见
        main.setVisible(true);

        // 检测数据库连接
        boolean initFlag = DsUtil.initDataSource(main);
        if (initFlag) {
            main.loadDep();
        }
    }

    private void setItems() {
        Main main = this;

        // 设置菜单
        addMenu();

        // 上部区域
        JPanel topPanel = new JPanel();
        topPanel.setPreferredSize(new Dimension(0, 120));
        topPanel.setLayout(new GridLayout(2, 1));
        this.add(topPanel, BorderLayout.NORTH);

        JPanel top1Panel = new JPanel();
        topPanel.add(top1Panel);
        top1Panel.setLayout(new FlowLayout(FlowLayout.LEFT));
        JLabel label = new JLabel("选择部门：");
        top1Panel.add(label);

        JComboBox<String> comboBox = getDepCmp();
        comboBox.setEditable(false);
        top1Panel.add(comboBox);

        JButton startButton = genStartButton(main);
        top1Panel.add(startButton);

        JButton stopButton = getStopBtn();
        stopButton.setEnabled(false);
        stopButton.addActionListener(e -> {
            getStartBtn().setEnabled(true);
            getExportBtn().setEnabled(true);
            getStopBtn().setEnabled(false);
            getScanField().setText("");
            getScanField().setEnabled(false);
            initStatusBar();
        });
        top1Panel.add(stopButton);

        JButton exportButton = genExportButton(main);
        top1Panel.add(exportButton);

        JPanel top2Panel = new JPanel();
        topPanel.add(top2Panel);
        top2Panel.setLayout(new FlowLayout(FlowLayout.LEFT));
        label = new JLabel("工卡扫描：");
        top2Panel.add(label);

        JTextField textField = genScanField(main);
        top2Panel.add(textField);

        // 下部区域
        JPanel p2 = this.getButtonPanel();
        p2.setLayout(new FlowLayout(FlowLayout.CENTER));
        p2.setPreferredSize(new Dimension(0, 40));
        this.add(p2, BorderLayout.SOUTH);

        // 中间区域
        JPanel center = new JPanel();
        center.setLayout(new GridLayout());
        this.add(center, BorderLayout.CENTER);

        JTable jTable = getTable();

        // 设置填充整个布局
        jTable.setFillsViewportHeight(true);

        // 禁止拖动表头
        jTable.getTableHeader().setReorderingAllowed(false);
        jTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);

        JScrollPane jScrollPane = new JScrollPane(jTable);
        center.add(jScrollPane);
    }

    private JButton genStartButton(Main main) {
        JButton startButton = getStartBtn();
        startButton.addActionListener(e -> {
            String depName = getDepCmp().getSelectedItem().toString();
            boolean startFlag = true;
            if (CharSequenceUtil.isBlank(depName)) {
                int val = JOptionPane.showConfirmDialog(main, "没有选择部门,确认开始记录？", "确认", JOptionPane.YES_NO_OPTION);
                startFlag = 0 == val;
            }
            if (startFlag) {
                getStartBtn().setEnabled(false);
                getDepCmp().setEnabled(false);
                getStopBtn().setEnabled(true);
                resetScanField();
                initStatusBar();
            }

        });
        return startButton;
    }

    private JTextField genScanField(Main main) {
        JTextField textField = this.getScanField();
        textField.setEnabled(false);
        textField.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyChar() == KeyEvent.VK_ENTER) {
                    String scanValue = getScanField().getText();
                    if (CharSequenceUtil.isNotBlank(scanValue)) {
                        // 禁用输入框,避免多次扫描
                        getScanField().setEnabled(false);
                        EsdEmp emp = DsUtil.findUserInfoByCardId(main, scanValue.trim());
                        if (emp == null) {
                            showFailMsg("获取用户信息失败！");
                            resetScanField();
                            SoundUtil.playFail(main);
                            return;
                        }

                        // 判断是否重复扫描
                        if (getScanSuccessUser().contains(emp.getNum())) {
                            showFailMsg(emp.getName() + "/" + emp.getNum() + "重复刷卡！");
                            resetScanField();
                            SoundUtil.playFail(main);
                            return;
                        }

                        // 判断是否本部门人员
                        if (!isSameDepartment(getDepCmp().getSelectedItem().toString(), emp)) {
                            showFailMsg(emp.getName() + "/" + emp.getNum() + "非本部门人员！");
                            resetScanField();
                            SoundUtil.playFail(main);
                            return;
                        }
                        addRow(emp);
                        showSuccessMsg(emp.getName() + "/" + emp.getNum() + "刷卡成功！");
                        addScanRecord(emp.getNum());
                        resetScanField();
                        SoundUtil.playSuccess(main);
                    }
                }
            }
        });
        return textField;
    }

    private JButton genExportButton(Main main) {
        JButton exportButton = getExportBtn();
        exportButton.setEnabled(false);
        exportButton.addActionListener(e -> {
            JFileChooser chooser = new JFileChooser();
            chooser.setMultiSelectionEnabled(false);
            chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
            int returnVal = chooser.showOpenDialog(null);
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                File file = chooser.getSelectedFile();
                ExcelUtil.export(file.getPath(), main);
                showSuccessMsg("文件导出成功！");
            }
        });
        return exportButton;
    }

    private void addRow(EsdEmp emp) {
        DefaultTableModel tableModel = getDefaultTableModel();
        tableModel.insertRow(0, new String[]{emp.getName(), emp.getNum(), CharSequenceUtil.isBlank(emp.getDep1()) ? ""
                : emp.getDep1(), CharSequenceUtil.isBlank(emp.getDep2()) ? "" : emp.getDep2(),
                CharSequenceUtil.isBlank(emp.getDep3()) ? "" : emp.getDep3(), "", ""});
    }

    private void addMenu() {
        JMenuBar menuBar = new JMenuBar();

        JMenu menu = new JMenu("设置");

        JMenuItem menuItem = new JMenuItem("数据库连接设置");
        menuItem.addActionListener(e -> new SettingDialog(this));

        menu.add(menuItem);
        menuBar.add(menu);
        this.setJMenuBar(menuBar);
    }

    /**
     * 判断是否本部门人员,只要5个部门中有一个能匹配上就行
     *
     * @param selectDep
     * @param emp
     * @return
     */
    private boolean isSameDepartment(String selectDep, EsdEmp emp) {
        // 没有选择部门,所有人都可以刷卡,不需要校验部门
        if (CharSequenceUtil.isBlank(selectDep)) {
            return true;
        }
        for (int idx = 5; idx >= 1; idx--) {
            String methodName = "getDep" + idx;
            Object value = ReflectUtil.invoke(emp, methodName);
            if (value != null && selectDep.equals(value.toString())) {
                return true;
            }
        }
        return false;
    }

    private void setFont() {
        Font defaultFont = new Font("宋体", Font.BOLD, 15);
        UIManager.put("Button.font", defaultFont);
        UIManager.put("ToggleButton.font", defaultFont);
        UIManager.put("RadioButton.font", defaultFont);
        UIManager.put("CheckBox.font", defaultFont);
        UIManager.put("ColorChooser.font", defaultFont);
        UIManager.put("ToggleButton.font", defaultFont);
        UIManager.put("ComboBox.font", defaultFont);
        UIManager.put("ComboBoxItem.font", defaultFont);
        UIManager.put("InternalFrame.titleFont", defaultFont);
        UIManager.put("Label.font", defaultFont);
        UIManager.put("List.font", defaultFont);
        UIManager.put("MenuBar.font", defaultFont);
        UIManager.put("Menu.font", defaultFont);
        UIManager.put("MenuItem.font", defaultFont);
        UIManager.put("RadioButtonMenuItem.font", defaultFont);
        UIManager.put("CheckBoxMenuItem.font", defaultFont);
        UIManager.put("PopupMenu.font", defaultFont);
        UIManager.put("OptionPane.font", defaultFont);
        UIManager.put("Panel.font", defaultFont);
        UIManager.put("ProgressBar.font", defaultFont);
        UIManager.put("ScrollPane.font", defaultFont);
        UIManager.put("Viewport", defaultFont);
        UIManager.put("TabbedPane.font", defaultFont);
        UIManager.put("TableHeader.font", defaultFont);
        UIManager.put("TextField.font", defaultFont);
        UIManager.put("PasswordFiled.font", defaultFont);
        UIManager.put("TextArea.font", defaultFont);
        UIManager.put("TextPane.font", defaultFont);
        UIManager.put("EditorPane.font", defaultFont);
        UIManager.put("TitledBorder.font", defaultFont);
        UIManager.put("ToolBar.font", defaultFont);
        UIManager.put("ToolTip.font", defaultFont);
        UIManager.put("Tree.font", defaultFont);
        SwingUtilities.updateComponentTreeUI(this);
    }

    public void loadDep() {
        // 清空缓存中的数据
        if (CollUtil.isNotEmpty(this.getDepList())) {
            getDepList().clear();
        }
        this.getDepCmp().removeAllItems();

        // 从数据库查询所有的部门
        List<EsdEmp> list = DsUtil.getAllDep(this);
        for (EsdEmp entity : list) {
            for (int idx = 5; idx >= 1; idx--) {
                String methodName = "getDep" + idx;
                Object val = ReflectUtil.invoke(entity, methodName);
                if (val != null && CharSequenceUtil.isNotBlank(val.toString())) {
                    this.addDep(val.toString());
                    break;
                }
            }
        }

        // 默认添加一个空的部门
        this.getDepCmp().addItem("");
        for (String dep : this.getDepList()) {
            this.getDepCmp().addItem(dep);
        }
    }

    private void resetScanField() {
        JTextField textField = this.getScanField();
        textField.setEnabled(true);
        textField.setText("");
        // 聚焦文本框
        textField.requestFocus();
    }

    private void initStatusBar() {
        this.showSuccessMsg("Ready!");
    }

    public void showSuccessMsg(String msg) {
        this.showMsg(msg, Color.GREEN);
    }

    public void showFailMsg(String msg) {
        this.showMsg(msg, Color.RED);
    }

    private void showMsg(String msg, Color bgColor) {
        JPanel panel = this.getButtonPanel();
        this.removeItems(panel);
        panel.setBackground(bgColor);
        JLabel label = new JLabel(msg);
        Font font = new Font("宋体", Font.BOLD, 25);
        label.setFont(font);
        panel.add(label);
    }

    private void removeItems(JPanel panel) {
        panel.removeAll();
        panel.revalidate();
        panel.repaint();
    }

    /**
     * 重置整个页面
     */
    public void resetFrame() {
        // 重新加载部门下拉框
        loadDep();
        getDepCmp().setEnabled(true);
        getStartBtn().setEnabled(true);
        getStopBtn().setEnabled(false);
        getExportBtn().setEnabled(false);
        getScanField().setText("");
        getScanField().setEnabled(false);
        getDefaultTableModel().getDataVector().clear();
        getTable().updateUI();
        getScanSuccessUser().clear();

        // 状态条初始化
        initStatusBar();
    }

    public JComboBox<String> getDepCmp() {
        return depCmp;
    }

    public List<String> getDepList() {
        return depList;
    }

    public void addDep(String dep) {
        if (this.depList == null) {
            this.depList = new ArrayList<>();
        }
        if (!this.depList.contains(dep)) {
            this.depList.add(dep);
        }
    }

    public JButton getStartBtn() {
        return startBtn;
    }

    public JButton getStopBtn() {
        return stopBtn;
    }

    public JTextField getScanField() {
        return scanField;
    }

    public JButton getExportBtn() {
        return exportBtn;
    }

    public JPanel getButtonPanel() {
        return buttonPanel;
    }

    public String[] getTableColumn() {
        return tableColumn;
    }

    public DefaultTableModel getDefaultTableModel() {
        return defaultTableModel;
    }

    public List<String> getScanSuccessUser() {
        return scanSuccessUser;
    }

    public void addScanRecord(String userId) {
        if (this.scanSuccessUser == null) {
            this.scanSuccessUser = new ArrayList<>();
        }
        this.scanSuccessUser.add(userId);
    }

    public JTable getTable() {
        return table;
    }
}